import type {
    WL_IDbMsgData,
    WL_IDbService,
    WL_IDbServiceStaff,
    WL_IDbSession,
    WL_IDbUserInfo
} from "@/proto/weilapb_external_data";
import type {WL_LoginParam} from "@/core/weila_datas";

function storePersistData(key: string, jsonData: string) {
    localStorage.setItem(key, jsonData);
}

function loadPersistData(key: string): string|null {
    return localStorage.getItem(key);
}


class Weila_MemDB {
    static instance: Weila_MemDB|undefined = undefined;
    private userStorage: Map<number, WL_IDbUserInfo>;
    private sessionStorage: Map<string, WL_IDbSession>;
    private msgDataStorage: WL_IDbMsgData[];
    private staffStorage: Map<number, WL_IDbServiceStaff>;
    private serviceStorage: Map<number, WL_IDbService>;
    private sessionNameStorage: Map<string, string>;
    private loginUserInfo: WL_IDbUserInfo|undefined;
    private msgSeq: number;
    private loginToken: string;
    private muteSession: Map<string, boolean>;

    public static getInstance(): Weila_MemDB {
        if (this.instance == undefined) {
            this.instance = new Weila_MemDB();
        }

        return this.instance;
    }

    constructor() {
        this.userStorage = new Map<number, WL_IDbUserInfo>();
        this.sessionStorage = new Map<string, WL_IDbSession>();
        this.sessionNameStorage = new Map<string, string>();
        this.msgDataStorage = [];
        this.staffStorage = new Map<number, WL_IDbServiceStaff>();
        this.serviceStorage = new Map<number, WL_IDbService>();
        this.loginUserInfo = undefined;
        this.msgSeq = 0;
        this.loginToken = '';
        this.muteSession = new Map<string, boolean>;
    }

    public enbaleAllSessionsMute(sessionIdList: string[], mute: boolean) {
        sessionIdList.forEach(value => {
            this.muteSession.set(value, mute);
        })
    }

    public enableSessionMute(sessionId: string, mute: boolean) {
        this.muteSession.set(sessionId, mute);
    }

    public isSessionMute(sessionId: string): boolean {
        if (this.muteSession.has(sessionId)) {
            return this.muteSession.get(sessionId)!;
        }

        this.muteSession.set(sessionId, false);
        return false;
    }

    public putSessionName(sessionId: string, sessionName: string) {
        this.sessionNameStorage.set(sessionId, sessionName);
    }

    public getSessionName(sessionId: string): string|undefined {
        return this.sessionNameStorage.get(sessionId);
    }

    public putLoginUserInfo(userInfo: WL_IDbUserInfo) {
        this.loginUserInfo = userInfo;
    }

    public getLoginUserInfo(): WL_IDbUserInfo|undefined {
        return this.loginUserInfo;
    }

    public putSession(session: WL_IDbSession) {
        const comboId = session.sessionId + "_" + session.sessionType;
        this.sessionStorage.set(comboId, session);
    }

    public getSession(sessionId: string, sessionType: number): WL_IDbSession|undefined {
        const comboId = sessionId + "_" + sessionType;
        if (this.sessionStorage.has(comboId)) {
            return this.sessionStorage.get(comboId);
        }

        return undefined;
    }

    public getSessionList(): WL_IDbSession[] {
        const sessionList: WL_IDbSession[] = [];
        this.sessionStorage.forEach(value => {
            sessionList.push(value);
        })

        return sessionList;
    }

    public delSession(session: WL_IDbSession) {
        const comboId = session.sessionId + "_" + session.sessionType;
        if (this.sessionStorage.has(comboId)) {
            this.sessionStorage.delete(comboId);
        }
    }

    public getMsgDataList(sessionId: string, sessionType: number): WL_IDbMsgData[] {
        return this.msgDataStorage.filter(value => {
            return value.sessionId === sessionId && value.sessionType === sessionType;
        });
    }

    public getLastMsgDatas(sessionId: string, sessionType: number, count: number): WL_IDbMsgData[] {
        const session = this.getSession(sessionId, sessionType);
        if (session) {
            const list = this.msgDataStorage.filter(value => {
                return value.sessionId == sessionId && value.sessionType == sessionType;
            });

            if (list.length <= count) {
                return list;
            }

            return list.slice(list.length - count, list.length);
        }

        return [];
    }

    public getLastMsgId(sessionId: string, sessionType: number): number {
        const session = this.getSession(sessionId, sessionType);
        if (session) {
            return session.lastMsgId;
        }

        return 0;
    }

    public putUser(userInfo: WL_IDbUserInfo) {
        this.userStorage.set(userInfo.userId, userInfo);
        storePersistData("userid_" + userInfo.userId, JSON.stringify(userInfo));
    }

    public putUsers(userInfos: WL_IDbUserInfo[]) {
        userInfos.forEach(value => {
            this.userStorage.set(value.userId, value);
            storePersistData("userid_" + value.userId, JSON.stringify(value));
        })
    }

    public getUser(userId: number): WL_IDbUserInfo|undefined {
        const data = loadPersistData("userid_" + userId);
        if (data) {
            try {
                const userInfo = JSON.parse(data);
                this.userStorage.set(userInfo.userId, userInfo);
            } catch (e) {
                console.error("本地没有存储用户信息")
            }
        }

        return this.userStorage.get(userId);
    }

    public putMsgDatas(msgDatas: WL_IDbMsgData[]) {
        msgDatas.forEach(msgData => {
            const index = this.msgDataStorage.findIndex(value => {
                return value.combo_id == msgData.combo_id;
            });

            if (index !== -1) {
                this.msgDataStorage.splice(index, 1, msgData);
            }else {
                this.msgDataStorage.push(msgData);
            }
        });

        this.msgDataStorage.sort((a, b) => {
            return a.created - b.created;
        });
    }

    public putMsgData(msgData: WL_IDbMsgData) {
        const index = this.msgDataStorage.findIndex(value => {
            return value.combo_id === msgData.combo_id ||
                value.preCombo_id === msgData.combo_id;
        });

        if (index !== -1) {
            this.msgDataStorage.splice(index, 1, msgData);
        }else {
            this.msgDataStorage.push(msgData);
        }

        this.msgDataStorage.sort((a, b) => {
            return a.created - b.created;
        });
    }

    public getMsgData(sessionId: string, sessionType: number, msgId: number): WL_IDbMsgData|undefined {
        const index = this.msgDataStorage.findIndex(value => {
            return value.sessionId == sessionId && value.sessionType == sessionType && value.msgId == msgId;
        })

        if (index !== -1) {
            return this.msgDataStorage[index];
        }

        return undefined;
    }

    public delMsgData(combo_id: string) {
        const index = this.msgDataStorage.findIndex(value => {
            return value.combo_id == combo_id;
        });

        if (index !== -1) {
            this.msgDataStorage.splice(index, 1);
        }
    }

    public getMsgDataByComboId(combo_id: string): WL_IDbMsgData|undefined {
        const index = this.msgDataStorage.findIndex(value => {
            return value.combo_id == combo_id;
        })

        if (index !== -1) {
            return this.msgDataStorage[index];
        }

        return undefined;
    }

    public getMsgDatasByComboIds(combo_ids: string[]): WL_IDbMsgData[] {
        return this.msgDataStorage.filter(value => {
            return combo_ids.indexOf(value.combo_id) !== -1;
        });
    }

    public getLastMsgDatasWithCount(sessionId: string, sessionType: number, count: number, fromMsgId: number): WL_IDbMsgData[] {
        const msgDatas = this.msgDataStorage.filter(value => {
            return value.sessionId == sessionId && value.sessionType == sessionType && value.msgId <= fromMsgId;
        });

        msgDatas.sort((a, b) => {
            return a.created - b.created;
        });

        if (msgDatas.length >= count) {
            return msgDatas.slice(msgDatas.length - count - 1, msgDatas.length);
        }

        return msgDatas;
    }

    public putStaff(staff: WL_IDbServiceStaff) {
        this.staffStorage.set(staff.userId, staff);
    }

    public getStaffs(userId: number): WL_IDbServiceStaff|undefined {
        return this.staffStorage.get(userId);
    }

    public putService(service: WL_IDbService) {
        this.serviceStorage.set(service.serviceId, service);
    }

    public getService(serviceId: number): WL_IDbService|undefined {
        return this.serviceStorage.get(serviceId);
    }

    public putMsgSeq(seq: number) {
        this.msgSeq = seq;
        storePersistData("MSG_SEQ", JSON.stringify(this.msgSeq));
    }

    public getMsgSeq(): number {
        const data = loadPersistData("MSG_SEQ");
        if (data) {
            this.msgSeq = JSON.parse(data);
        }

        return this.msgSeq;
    }

    public putLoginToken(token: string) {
        this.loginToken = token;
    }

    public getLoginToken(): string {
        return this.loginToken;
    }
}

export {Weila_MemDB};
